package csc.transformation;

import csc.approximation.LcaApproximationEquation;
import csc.approximation.AcaApproximationEquation;
import csc.main.Colors;
import csc.triangulation.Vector3d;
import java.util.List;

/**
 * Class is used to transform coordinates using stored approximation functions.
 * @author Stanislau Dubrouski
 */
public class CoordinatesTransformer {

    public enum ColorPair {

        FIRST(0), SECOND(1), THIRD(2);
        private final int id;

        ColorPair(int id) {
            this.id = id;
        }

        public int getValue() {
            return id;
        }
    };

    private final List<List<LcaApproximationEquation>> lca;
    private final List<AcaApproximationEquation> aca;

    /**
     * 
     * @param lca
     * @param aca
     */
    public CoordinatesTransformer(List<List<LcaApproximationEquation>> lca, List<AcaApproximationEquation> aca) {
        this.lca = lca;
        this.aca = aca;
    }

    /**
     * Transforms coordinates using stored approximation functions and specified color channel.
     * @param x
     * @param y
     * @param z
     * @param refColor
     * @param toTransform
     * @return vector with transsformed coordinates
     */
    public Vector3d transformCoordinates(float x, float y, float z, Colors refColor, Colors toTransform) {
        Vector3d original = new Vector3d(x, y, z);
        return this.transformCoordinates(original, refColor, toTransform);
    }

    /**
     * Transforms coordinates using stored approximation functions and specified color channel.
     * @param original
     * @param refColor
     * @param toTransform
     * @return vector with transsformed coordinates
     */
    public Vector3d transformCoordinates(Vector3d original, Colors refColor, Colors toTransform) {
        //decide what color pair will be used
        int colorPair = 0;
        for (int i = 0; i < aca.size(); i++) {
            if ((aca.get(i).getColorFrom() == refColor) || (aca.get(i).getColorFrom() == toTransform)) {
                if ((aca.get(i).getColorTo() == refColor) || (aca.get(i).getColorTo() == toTransform)) {
                    colorPair = i;
                    break;
                }
            }
        }

        //depending on position of refColor in selected color pair, get direction of correction
        int sign;
        
        if (aca.get(colorPair).getColorFrom() == refColor) {
            sign = 1;
        } else {
            sign = -1;
        }

        Vector3d transformed = new Vector3d(original);
        float xShift = lca.get(colorPair).get(0).calculateEstimatedShiftValue(transformed.getX(), transformed.getY());
        float yShift = lca.get(colorPair).get(1).calculateEstimatedShiftValue(transformed.getX(), transformed.getY());
        float zShift = aca.get(colorPair).calculateEstimatedShiftValue(transformed.getX(), transformed.getY());
        
        transformed.setX(original.getX() + xShift * sign);
        transformed.setY(original.getY() + yShift * sign);
        transformed.setZ(original.getZ() + zShift * sign);

        return transformed;
    }

    public boolean includesColor(Colors color) {
        boolean includesColor = false;
        for (AcaApproximationEquation eq : aca){
            if (eq.includesColor(color)){
                includesColor = true;
            }
        }
        return includesColor;
    }
}
